import { Label, NodePool, _decorator, math, sp, v2 } from 'cc';
import { BaseFightBoxComp } from './BaseFightBoxComp';
import { BaseFightLogic } from './core/BaseFightLogic';
import IBaseFightAttribute from './core/data/IBaseFightAttribute';
import { LifeEnum } from './core/enum/LifeEnum';
import IBaseFight from './core/fight/IBaseFight';
import { ActionEnum } from './enum/MonsterActionEnum';
import SimpleSpineAttack from './fightAction/SimpleSpineAttack';
const { ccclass, property } = _decorator;

@ccclass('MonsterBaseFightComp')
export class MonsterBaseFightComp extends BaseFightBoxComp {
    /****************************************************************************************************************
     *Readonly 常量
     ****************************************************************************************************************/
    /****************************************************************************************************************
     *Property 定义变量
     ****************************************************************************************************************/
    /**
     * 当前行动状态
     */
    private _statue: ActionEnum = ActionEnum.SHOW;

    /**
     * 当前的敌人集合
     */
    protected enemySet: Set<IBaseFight> = new Set();


    /**
     * 倒计时(执行完一个行动到下一个行动的间隔)
     */
    protected downTime: number = 0;
    /***************************************************************
     *PropertyUI 引用的控件
     ***************************************************************/
    @property({ group: { name: 'View', id: '3' }, type: sp.Skeleton, tooltip: `播放的骨骼动画` })
    protected spine: sp.Skeleton = undefined!;

    @property({ group: { name: 'View', id: '3' }, type: Label, tooltip: `血量文本组件` })
    private hpLabel: Label = undefined!;

    /**
     * 怪物回收对象池引用
     */
    private pool: NodePool = undefined!;
    /****************************************************************************************************************
     * Lifecycle 生命周期相关方法
     ****************************************************************************************************************/
    protected update(dt: number): void {

        if (this.downTime <= 0) {
            return;
        }

        this.downTime -= dt;

        if (this.downTime <= 0) {
            this.statue = ActionEnum.IDLE;
        }
    }
    /****************************************************************************************************************
     * Public 公有方法
     ****************************************************************************************************************/
    public init(value: IBaseFightAttribute): void {
        super.init(value);
        this.fightAction = new SimpleSpineAttack(this, this.spine);
    }

    public fightStart(): void {
        super.fightStart();
        this.monsterFightStart();
    }

    public action(): Promise<boolean> {
        let promise = super.action();
        return promise;
    }

    /********************************
     * 对象池相关方法
     ********************************/
    /**
     * 对象池使用时候使用
     */
    public reuse(args: any[]) {
        let a: IBaseFightAttribute = args[0];
        this.init(a);
        this.pool = args[1];
    }
    /**
     * 对象池回收时候使用
     */
    public unuse() {
        this.node.setPosition(0, 0, 0);
        this.node.eulerAngles = math.Vec3.ZERO;
        this.node.setRotationFromEuler(0, 0, 0);
        this.body.linearVelocity = math.Vec2.ZERO;
        this.body.angularVelocity = 0;
        this.lifeState = LifeEnum.INIT;
    }
    /****************************************************************************************************************
     * private 私有方法
     ****************************************************************************************************************/
    private monsterFightStart(): void {
        this.statue = ActionEnum.RUN;
    }

    /**
     * 状态改变时候调用
     */
    private updateStatue(value: ActionEnum) {
        switch (value) {
            case ActionEnum.SHOW:
                break;
            case ActionEnum.RUN:
                this.playAnimation('run', true);
                this.body.linearVelocity = v2(0, 0)
                break;
            case ActionEnum.IDLE:
                this.playAnimation('idle', true);
                this.body.linearVelocity = v2(0, 0);
                let promise = this.action();
                promise.then(
                    (value) => {
                        this.statue = value ? ActionEnum.DETAIL : ActionEnum.RUN;
                        if (value) {
                            this.downTime = 3;
                        }
                    }, (error) => {
                        error(error)
                    }
                )
                break;
            case ActionEnum.DETAIL:
                this.playAnimation('idle', true);
                this.body.linearVelocity = v2(0, 0);
                break;
            default:
                break;
        }
    }


    /**
     * 回收当前怪物对象池
     */
    protected recycleMonster(): void {
        this.scheduleOnce(() => {
            if (this.pool) {
                this.pool.put(this.node);
            } else {
                this.node.removeFromParent();
            }
        }, 0);
    }
    /**************************************************
     * Utils
     *************************************************/
    protected playAnimation(name: string, loop: boolean = false): void {
        this.spine?.setAnimation(0, name, loop)
    }

    /*******************************************
     * Override
     *******************************************/
    protected override updateHp(hp: number): void {
        super.updateHp(hp);

        if (this.hpLabel) {
            this.hpLabel.string = `${hp}/${this.maxHp}`;
        }
    }

    public override fightDead(): void {
        super.fightDead();
        let promise: Promise<void> = new Promise((resolve, reject) => {
            this.spine.setAnimation(0, "die", false);
            this.spine.setCompleteListener(() => {
                resolve();
            });
            this.spine.setInterruptListener(() => {
                resolve();
            });
        });
        promise.then(
            (value) => {
                this.recycleMonster();
            }, (error) => {
            }
        )
    }
    /****************************************************************************************************************
     * Property Get && Set 属性的 get && set 函数
     ****************************************************************************************************************/
    /**********************
     * 
     ********************/
    public get enemy(): BaseFightLogic[] {
        let array = Array.from(this.bodyFightSet);
        array = array.filter(v => v.lifeState != LifeEnum.DEAD)
        return array;
    }

    public get statue(): ActionEnum {
        return this._statue;
    }
    public set statue(value: ActionEnum) {
        if (this._statue === value) {
            return;
        }

        this._statue = value;
        this.updateStatue(value);
    }
}


